var SelectLevelLayer = cc.Layer.extend({
    _util: new Util(),
    _manage: null,
    _node00: {
        key: "node00"
    },
    _node01: {
        key: "node01"
    },
    _node10: {
        key: "node10"
    },
    _btnShop: {
        key: "btnShop"
    },
    _txtBucks: {
        key: "txtBucks"
    },
    _layer: null,
    _cells: new Object(),
    _kMaxCellsOfPage: 12,
    ctor: function(){
        this._super();
        if ('touches' in sys.capabilities) 
            this.setTouchEnabled(true);
        else if ('mouse' in sys.capabilities) 
            this.setMouseEnabled(true);
    },
    init: function(){
        var bRet = false;
        if (this._super()) {
            this._util.onAssignCCBMemberVariable(this.assignActive());
            var layerNode = this._util.newLayerFromCCB(s_selectLevel_ccbi, this);
            this._layer = layerNode;
            this._txtBucks.instance.setVisible(false);
            this._btnShop.instance.setVisible(false);
            this._manage = this._util.ccbReader.getAnimationManager();
            this._manage.setCompletedAnimationCallback(this, this.onCCBAnimEnd);
            
            if (layerNode != null) {
                this.addChild(layerNode);
            }
            this.intCell();
            bRet = true;
        }
        return bRet;
    },
    assignActive: function(){
        var arr = new Array();
        var $this = this;
        arr.push(this._node00);
        arr.push(this._node01);
        arr.push(this._node10);
        arr.push(this._btnShop);
        arr.push(this._txtBucks);
        arr.push({
            key: "btnMainmenu",
            callback: function(){
                sound.playButtonSound();
                if ($this._manage.getRunningSequenceName() == null) {
                    $this._manage.runAnimations("Out");
                }
                $this.mOutFunc = function(){
                    this.cleanUp();
                    game.backToMainMenu();
                }
            }
        });
        arr.push({
            key: "btnLeft",
            callback: function(){
                $this.onLeft();
            }
        });
        arr.push({
            key: "btnRight",
            callback: function(){
                $this.onRight();
            }
        });
        return arr;
    },
    intCell: function(){
        var elemsNumPerRaw = 3;
        var startX = this._node00.instance.getPositionX();
        var startY = this._node00.instance.getPositionY();
        var gapW = startX - this._node01.instance.getPositionX();
        var gapH = this._node10.instance.getPositionY() - startY;
        
        startX = startX - gapW * Math.floor(elemsNumPerRaw / 2);
        
        var x = startX, y = startY, ix = 0;
        var $this = this;
        var placeCellElem = function(elem, x, y){
            $this._layer.addChild(elem);
            elem.setAnchorPoint(cc.p(0.5, 0.5));
            elem.setPosition(x, y);
            elem.setVisible(false);
        }
        for (var i = 0; i < this._kMaxCellsOfPage; i++) {
            this._cells[i] = {
                id: 0
            }
            var xx = x + ix * gapW;
            this._cells[i].bgPlayed = cc.Sprite.create(s_LevelButton);
            placeCellElem(this._cells[i].bgPlayed, xx, y);
            this._cells[i].bgCur = cc.Sprite.create(s_LevelButtonPressed);
            placeCellElem(this._cells[i].bgCur, xx, y);
            this._cells[i].bgDisable = cc.Sprite.create(s_LevelButtonDisabled);
            placeCellElem(this._cells[i].bgDisable, xx, y);
            this._cells[i].bgLock = cc.Sprite.create(s_LevelButtonLocked);
            placeCellElem(this._cells[i].bgLock, xx, y);
            this._cells[i].lbl = cc.LabelBMFont.create("0", s_FontEng_fnt);
            placeCellElem(this._cells[i].lbl, xx, y);
            ix = ix + 1;
            if (ix == elemsNumPerRaw) {
                ix = 0;
                y = y + gapH;
            }
        }
        
        var pages = Math.floor((this._curPlayLevelId - 0.5) / this._kMaxCellsOfPage);
        this._curStartLevelId = this._kMaxCellsOfPage * pages + 1;
        
        this.fillPage();
    },
    cleanUp: function(){
        this._cells = new Object();
    },
    _curPlayLevelId: null,
    _maxPlayableLevelId: null,
    _maxLevelId: null,
    _curStartLevelId: null,
    fillPage: function(){
        for (var i = 0; i < this._kMaxCellsOfPage; i++) {
            var id = this._curStartLevelId + i;
            var lbl = this._cells[i].lbl;
            if (id <= this._maxPlayableLevelId) {
                lbl.setVisible(true);
                lbl.setString(id);
                this._cells[i].id = id;
            } else {
                lbl.setVisible(false);
                this._cells[i].id = 0;
            }
            
            this._cells[i].bgPlayed.setVisible(false);
            this._cells[i].bgCur.setVisible(false);
            this._cells[i].bgDisable.setVisible(false);
            this._cells[i].bgLock.setVisible(false);
            
            if (id < this._curPlayLevelId) {
                lbl.setColor(cc.c3(220, 50, 50));
                this._cells[i].bgPlayed.setVisible(true)
            } else if (id == this._curPlayLevelId) {
                lbl.setColor(cc.c3(255, 255, 255));
                this._cells[i].bgCur.setVisible(true);
            } else if (id <= this._maxPlayableLevelId) {
                lbl.setColor(cc.c3(150, 150, 150));
                this._cells[i].bgDisable.setVisible(true);
            } else if (id <= this._maxLevelId) {
                this._cells[i].bgLock.setVisible(true);
            }
        }
    },
    onLeft: function(){
        if (this._curStartLevelId == 1) {
            return;
        }
        this._curStartLevelId = this._curStartLevelId - this._kMaxCellsOfPage;
        this.fillPage();
    },
    onRight: function(){
        if (this._curStartLevelId + this._kMaxCellsOfPage > this._maxLevelId) {
            return;
        }
        this._curStartLevelId = this._curStartLevelId + this._kMaxCellsOfPage;
        this.fillPage();
    },
    mOutFunc: null,
    onCCBAnimEnd: function(){
        var animName = this._manage.getLastCompletedSequenceName();
        if (animName == "Out") {
            if (this.mOutFunc != null) {
                this.mOutFunc();
                this.mOutFunc = null;
            }
        } else {
        }
    },
    onMouseUp: function(event){
        this.onTouch(event);
    },
    onTouchesEnded: function(touches, event){
        if (touches.length <= 0) 
            return;
        var touch = touches[0];
        this.onTouch(touch);
    },
    onTouch: function(event){
        var $this = this;
        var selected = 0;
        var x = event._point.x, y = event._point.y;
        for (var i = 0; i < this._kMaxCellsOfPage; i++) {
            if (this._cells[i].id > 0 && this._cells[i].id <= this._curPlayLevelId) {
                var obj = this._cells[i].bgPlayed;
                if (util.isSelectSprite(this._cells[i].bgPlayed, x, y)) {
                    selected = this._cells[i].id;
                }
            }
        }
        if (selected > 0) {
            cc.log('sel:' + selected);
            sound.playButtonSound();
            
            if (this._manage.getRunningSequenceName() != "Out") {
                this._manage.runAnimations("Out");
                this.mOutFunc = function(){
                    $this.cleanUp();
                    game.playLevel(selected);
                }
            }
        }
    }
});

SelectLevelLayer.create = function(){
    var sl = new SelectLevelLayer();
    if (sl && sl.init()) {
        return sl;
    }
    return null;
}

SelectLevelLayer.scene = function(){
    var scene = cc.Scene.create();
    var layer = SelectLevelLayer.create();
    scene.addChild(layer);
    return scene;
}

var PlayLevelLayer = cc.Layer.extend({
    _util: new Util(),
    _manage: null,
    _level: config.nextUnpassLevel(),
    _btnPause: {
        key: "btnPause"
    },
    _sprPen: new Array({
        key: "sprPen1"
    }, {
        key: "sprPen2"
    }, {
        key: "sprPen3"
    }, {
        key: "sprPen4"
    }),
    _txtLevelId: {
        key: "txtLevelId"
    },
    _txtTime: {
        key: "txtTime"
    },
    _nodeBoardCenter: {
        key: "nodeBoardCenter"
    },
    GAME_RECT_X_CENTER: config.designWidth / 2,
    GAME_RECT_Y_CENTER: config.designHeight / 2,
    _mBaseLayer: null,
    _defaultPenPosY: null,
    ctor: function(){
        this._super();
        if ('touches' in sys.capabilities) 
            this.setTouchEnabled(true);
        else if ('mouse' in sys.capabilities) 
            this.setMouseEnabled(true);
    },
    init: function(){
        var bRet = false;
        if (this._super()) {
            this._util.onAssignCCBMemberVariable(this.assignActive());
            var layerNode = this._util.newLayerFromCCB(s_level_ccbi, this);
            this._mBaseLayer = layerNode;
            this._manage = this._util.ccbReader.getAnimationManager();
            this._manage.setCompletedAnimationCallback(this, this.onCCBAnimEnd);
            
            if (layerNode != null) {
                this.addChild(layerNode);
            }
            
            this._defaultPenPosY = this._sprPen[0].instance.getPositionY();
            
            var nodeBoardCenter = this._nodeBoardCenter.instance;
            this.GAME_RECT_X_CENTER = nodeBoardCenter.getPositionX();
            this.GAME_RECT_Y_CENTER = nodeBoardCenter.getPositionY();
            
            LevelHelper.init();
            this.layoutBoardSprite(g_filledColorSpr, 2);
            layerNode.addChild(g_filledColorSpr);
            
            this.layoutBoardSprite(g_flashRegionSpr, 2);
            layerNode.addChild(g_flashRegionSpr);
            g_flashRegionSpr.setVisible(false);
            
            //add border sprite
            var sprBoarder = cc.Sprite.create(s_GgGame);
            this.layoutBoardSprite(sprBoarder, 1);
            layerNode.addChild(sprBoarder, 2);
            
            this.runLevel();
            
            bRet = true;
        }
        return bRet;
    },
    assignActive: function(){
        var arr = new Array();
        var $this = this;
        this._btnPause.callback = function(){
            sound.playButtonSound();
            if (!$this._levelPause.isPlayingAnim()) {
                if ($this._levelState != $this._levelPause) {
                    $this.setState($this._levelPause);
                } else {
                    $this._levelPause.onResume();
                }
            }
        }
        arr.push(this._btnPause);
        arr.push(this._sprPen[0]);
        arr.push(this._sprPen[1]);
        arr.push(this._sprPen[2]);
        arr.push(this._sprPen[3]);
        arr.push(this._txtLevelId);
        arr.push(this._txtTime);
        arr.push(this._nodeBoardCenter);
        return arr;
    },
    callbackAnimEnd: null,
    onCCBAnimEnd: function(){
        var animName = this._manage.getLastCompletedSequenceName();
        if (animName == "in" && this.callbackAnimEnd != null) {
            this.callbackAnimEnd();
        }
    },
    setPen: function(id, textureName){
        var oldPen = this._sprPen[id].instance;
        var layer = oldPen.getParent();
        var newPen = cc.Sprite.create(dirImg + textureName);
        this._sprPen[id].instance = newPen;
        newPen.setPosition(oldPen.getPosition());
        newPen.setPositionY(this._defaultPenPosY);
        layer.addChild(newPen);
        layer.setZOrder(2);
        oldPen.removeFromParent(true);
    },
    resetPen: function(){
        this._levelPlay.currentPenId = 0;
        this._sprPen[0].instance.setPositionY(this._sprPen[0].instance.getPositionY() + this._levelPlay.CURRENT_PEN_OFFSET);
    },
    initLevel: function(){
        resetLevel(); //C++函数
        //随机选择4种颜色，并设置图片
        var penColors = util.getRandomSequence(4);
        
        //        var colorTextures = ["board_colour11.png", "board_colour12.png", "board_colour21.png", "board_colour22.png", "board_colour31.png", "board_colour32.png", "board_colour41.png", "board_colour42.png"];
        var colorTextures = [[252, 233, 4], [94, 207, 7], [233, 11, 35], [1, 93, 254], [252, 184, 6], [1, 207, 129], [240, 90, 1], [0, 162, 250]]
        var PenTextures = ["button_pencile_11.png", "button_pencile_12.png", "button_pencile_21.png", "button_pencile_22.png", "button_pencile_31.png", "button_pencile_32.png", "button_pencile_41.png", "button_pencile_42.png"];
        
        //使用第一组（前4种）或第二组（后4种）
        var groupOffset = parseInt(Math.random() * 2) * 4;
        
        for (var i = 0; i < 4; i++) {
            var idx = penColors[i] + groupOffset;
            setColorTexture(i, colorTextures[idx]); //C++函数
            this.setPen(i, PenTextures[idx]);
        }
        
        this.resetPen();
        
        //reset time
        this._leftTime = parseInt(storage.get('LEVEL_MAX_TIME'));
        
        //reset fail count
        storage.set('failCount', 0);
        storage.set('levelScore', 0);
        storage.set('buyTimeCount', 0);
        this.setTime(this._leftTime);
    },
    _leftTime: null,
    _sprLevel: null,
    _levelState: null,
    runLevel: function(){
        var levelIndex = this._level;
        if (this._sprLevel != null) {
            this._sprLevel.removeFromParent(true);
            this._sprLevel = null;
        }
        this._sprLevel = cc.Sprite.create(level_png(levelIndex));
        this.layoutBoardSprite(this._sprLevel, 2);
        this._mBaseLayer.addChild(this._sprLevel, 2);
        
        //set level id txt
        this._txtLevelId.instance.setString(levelIndex);
        this._txtLevelId.instance.setPosition(80, 100)
        
        this.openLevel(levelIndex) //C++函数
        this.initLevel();
        
        this.callbackAnimEnd = null;
        
        this.startLevel();
        this.setState(this._levelPlay);
        
    },
    _isTimerPaused: true,
    _mHasStartTime: false,
    startLevel: function(){
        cc.log('---start level---');
        this._mHasStartTime = false;
    },
    openLevel: function(levelIndex){
        loadLevel(level_pda(levelIndex));
    },
    pauseLevel: function(){
        cc.log('---pause level---');
        this.pauseTimer();
        this._btnPause.instance.setEnabled(false);
    },
    pauseLevelPlay: function(){
        cc.log('---pause level play---');
        this.pauseTimer();
    },
    resumeLevel: function(){
        cc.log('---resume level---')
        this.resumeTimer();
        this._btnPause.instance.setEnabled(true);
    },
    retryLevel: function(){
        cc.log('---retry level---')
        this.endTimer();
        unLoadLevel();
        this.initLevel();
        this.startLevel();
        this.setState(this._levelPlay);
    },
    exitLevel: function(){
        cc.log('---exit level---')
        if (this._sprLevel != null) {
            this._sprLevel.removeFromParent(true);
            this._sprLevel = null;
        }
        this.endTimer();
        unLoadLevel(); //C++函数
        this._levelState = null;
    },
    setState: function(state){
        cc.log('set level state to ' + state);
        
        if (this._levelState != null && this._levelState.onExit != null) {
            this._levelState.onExit();
        }
        
        this._levelState = state;
        
        if (this._levelState.onEnter != null) {
            this._levelState.onEnter(this);
        }
    },
    addFailCount: function(){
        storage.set('failCount', 1 + parseInt(storage.get('failCount')));
    },
    setTime: function(time){
        this._txtTime.instance.setString(time);
        this._txtTime.instance.setPosition(170, 100)
    },
    layoutBoardSprite: function(spr, scale){
        spr.setPosition(this.GAME_RECT_X_CENTER, this.GAME_RECT_Y_CENTER);
        spr.setAnchorPoint(cc.p(0.5, 0.5));
        spr.setScale(scale)
    },
    _schedulerEntryTimer: null,
    startTimer: function(){
        if (!this._mHasStartTime) {
            this._mHasStartTime = true
            if (this.onTimer != null) {
                //scheduler.unscheduleScriptEntry(this._schedulerEntryTimer);
                this.unschedule(this.onTimer);
            }
            this.schedule(this.onTimer, 1);
            this._isTimerPaused = false;
        }
    },
    onTimer: function(){
        if (!this._isTimerPaused) {
            this._leftTime -= 1;
            this.setTime(this._leftTime)
            if (this._leftTime <= 0) {
                cc.log('---time up---');
                this.pauseLevel();
                sound.playFailSound();
                this.setState(this._levelFail);
            }
        }
    },
    pauseTimer: function(){
        this._isTimerPaused = true;
    },
    resumeTimer: function(){
        this._isTimerPaused = false;
    },
    endTimer: function(){
        if (this.onTimer != null) {
            this.unschedule(this.onTimer);
        }
    },
    calcScore: function(){
        var scoreTime = this._leftTime;
        var score = this._level * 200 + (scoreTime - parseInt(storage.get('failCount')) * 5) * 20;
        if (score < 100) {
            score = 100;
        }
        storage.set('levelScore', parseInt(score));
    },
    _levelPause: LevelPause,
    _levelPlay: LevelPlay,
    _levelWin: LevelWin,
    _levelFail: LevelFail,
    _levelAllDone: LevelAllDone,
    onMouseUp: function(event){
        this.onTouch(event);
    },
    onTouchesEnded: function(touches, event){
        if (touches.length <= 0) 
            return;
        var touch = touches[0];
        this.onTouch(touch);
    },
    onTouch: function(event){
        this._levelPause.onTouch(event);
        this._levelPlay.onTouch(event);
    }
});

PlayLevelLayer.create = function(){
    var sl = new PlayLevelLayer();
    if (sl && sl.init()) {
        return sl;
    }
    return null;
}
